home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 11 / Cream of the Crop 11-1.iso / games / ted5.zip / IGRABSRC.ZIP / GRABCGA.C < prev    next >
C/C++ Source or Header  |  1993-02-04  |  10KB  |  509 lines

  1. ////////////////////////////////////////////////////////////
  2. //
  3. // CGA GRABBING
  4. //
  5. // NOTE: THE LOADED CGA SCREEN AT "LBMSCREEN" & "MASKSCREEN"
  6. // IS NOT "CGA-MUNGED", IT'S LINEARLY ARRANGED! YAY!
  7. //
  8. ////////////////////////////////////////////////////////////
  9. #include "igrab.h"
  10. #pragma hdrstop
  11.  
  12. ////////////////////////////////////////////////////////////
  13. //
  14. // CGAblit : blits a CGA shape from memory to the CGA screen
  15. //
  16. ////////////////////////////////////////////////////////////
  17. void CGAblit(int x,int y,int width,int height,char huge *buffer)
  18. {
  19.  unsigned ESreg,DIreg,SIreg,DSreg,where,owidth,addx;
  20.  
  21.  if (noshow || SkipToStart)
  22.    return;
  23.  // Preclipping
  24.  if (x<0 || y<0)
  25.    return;
  26.  
  27.  if (x>79 || y>199)
  28.    globalx=globaly=globalmaxh=x=y=0;
  29.  
  30.  addx=0;
  31.  if (x+width>79)
  32.    {
  33.     owidth=width;
  34.     width=80-x;
  35.     addx=owidth-width;
  36.    }
  37.  if (y+height>199)
  38.    {
  39.     height=200-y;
  40.    }
  41.  
  42.  DSreg=FP_SEG(buffer);
  43.  SIreg=FP_OFF(buffer);
  44.  where=(y/2)*80+0x2000*(y&1)+x;
  45.  
  46.  asm    push    si
  47.  asm    push    di
  48.  asm    push    ds
  49.  asm    pushf
  50.  
  51.  asm    cld
  52.  asm    mov    ax,0xb800
  53.  asm    mov    es,ax
  54.  asm    mov    si,[SIreg]
  55.  asm    mov    ax,[DSreg]
  56.  asm    mov    ds,ax
  57.  
  58.  asm    mov    bx,[y]
  59.  asm    mov    di,[where]
  60.  asm    mov    dx,[height]
  61.  LOOP1:
  62.  asm    mov    cx,[width]
  63.  asm    rep movsb
  64.  asm    mov    cx,[addx]    // any to finish up horizontally?
  65.  asm    jcxz    LOOP1a
  66.  asm    rep lodsb
  67.  
  68.  LOOP1a:
  69.  asm    sub    di,[width]
  70.  asm    xor    di,0x2000    // calculate next CGA line
  71.  asm    inc    bx
  72.  asm    and    bx,1
  73.  asm    or    bx,bx
  74.  asm    jnz    LOOP1a0
  75.  asm    add    di,80
  76.  
  77.  LOOP1a0:
  78.  asm    dec    dx
  79.  asm    jnz    LOOP1
  80.  
  81.  asm    popf
  82.  asm    pop    ds
  83.  asm    pop    di
  84.  asm    pop    si
  85. }
  86.  
  87.  
  88. ////////////////////////////////////////////////////////////
  89. //
  90. // DoCGAblit : handles output of CGA grabs to the screen
  91. //
  92. ////////////////////////////////////////////////////////////
  93. void DoCGAblit(int x,int y,int width,int height)
  94. {
  95.  if (noshow || SkipToStart)
  96.    return;
  97.  
  98.  if (nostacking)
  99.    {
  100.     globalx=x;
  101.     globaly=y;
  102.    }
  103.  
  104.  CGAblit(globalx,globaly,width,height,databuffer+offset);
  105.  if (!nostacking)
  106.    {
  107.     globalx+=width;
  108.     if (globalmaxh<height)
  109.       globalmaxh=height;
  110.     if (globalx>80-width)
  111.       {
  112.        globaly+=globalmaxh;
  113.        globalx=globalmaxh=0;
  114.       }
  115.    }
  116. }
  117.  
  118.  
  119. ////////////////////////////////////////////////////////////
  120. //
  121. // CGAgrab : grabs any CGA shape from the screen buffer in main memory
  122. //           with INLINE asm for *FAST* grab!
  123. //         Of course, by John Romero!
  124. //
  125. // NOTE: I expect X & WIDTH to be in BYTE values, not pixels!
  126. //
  127. ////////////////////////////////////////////////////////////
  128. void CGAgrab(int x,int y,int width,int height,unsigned offset)
  129. {
  130.  unsigned ESreg,DIreg,SIreg,DSreg,scrnwid,loc;
  131.  
  132.  scrnwid=CurrentLBM.width/4;
  133.  loc=y*scrnwid+x;
  134.  
  135.  // FROM
  136.  SIreg=FP_OFF(lbmscreen)+(loc&15);
  137.  DSreg=FP_SEG(lbmscreen)+(loc/16);
  138.  
  139.  // TO
  140.  ESreg=FP_SEG(databuffer+offset);
  141.  DIreg=FP_OFF(databuffer+offset);
  142.  
  143.  asm        push    si
  144.  asm        push    di
  145.  asm        push    ds
  146.  
  147.  asm        mov    bx,height
  148.  asm        mov    dx,width
  149.  
  150.  asm        mov    es,ESreg
  151.  asm        mov    di,DIreg
  152.  asm        mov    si,SIreg
  153.  asm        mov    ax,DSreg
  154.  asm        mov    ds,ax
  155.  asm        cld
  156.  
  157.  LOOP1:
  158.  
  159.  asm        mov    cx,dx
  160.  asm        rep movsb
  161.  
  162.  asm        sub    si,dx
  163.  asm        add    si,scrnwid
  164.  asm        dec    bx
  165.  asm        jnz    LOOP1
  166.  
  167.  asm        pop    ds
  168.  asm        pop    di
  169.  asm        pop    si
  170.  
  171.  offset+=width*height;
  172. }
  173.  
  174. ////////////////////////////////////////////////////////////
  175. ////////////////////////////////////////////////////////////
  176. //
  177. // MASKED STUFF
  178. //
  179. ////////////////////////////////////////////////////////////
  180. ////////////////////////////////////////////////////////////
  181.  
  182.  
  183. ////////////////////////////////////////////////////////////
  184. //
  185. // CGAMblit : blits a CGA masked shape from memory to the CGA screen
  186. //
  187. ////////////////////////////////////////////////////////////
  188. void CGAMblit(int x,int y,int width,int height,char huge *buffer)
  189. {
  190.  unsigned MASKoff,DATAoff,ESreg,DIreg,SIreg,DSreg,where,oheight,owidth,addx;
  191.  
  192.  if (noshow || SkipToStart)
  193.    return;
  194.  // Preclipping
  195.  if (x<0 || y<0)
  196.    return;
  197.  
  198.  addx=0;
  199.  owidth=width;
  200.  oheight=height;
  201.  
  202.  if (x+width>79)
  203.    {
  204.     width=80-x;
  205.     addx=owidth-width;
  206.    }
  207.  if (y+height>199)
  208.    {
  209.     height=200-y;
  210.    }
  211.  
  212.  DSreg=FP_SEG(buffer);
  213.  MASKoff=FP_OFF(buffer);
  214.  DATAoff=FP_OFF((char far *)buffer+owidth*oheight);
  215.  where=(y/2)*80+0x2000*(y&1)+x;
  216.  
  217.  asm    push    si
  218.  asm    push    di
  219.  asm    push    ds
  220.  asm    pushf
  221.  
  222.  asm    mov    dx,[DATAoff]
  223.  asm    mov    ds,[DSreg]
  224.  
  225.  asm    mov    si,[MASKoff]
  226.  asm    mov    di,[where]
  227.  asm    mov    ax,0xb800
  228.  asm    mov    es,ax
  229.  
  230.  asm    mov    bl,[BYTE PTR y]
  231.  asm    mov    bh,[BYTE PTR height]
  232.  LOOP1:
  233.  asm    mov    cx,[width]
  234.  LOOP1c:
  235.  asm    mov    al,[es:di]
  236.  asm    and    al,[si]        // get mask byte (SI=mask data)
  237.  asm    inc    si
  238.  asm    xchg    si,dx        // SI now = CGA data
  239.  asm    or    al,[si]
  240.  asm    inc    si
  241.  asm    xchg    si,dx        // SI now = MASK data
  242.  asm    stosb
  243.  asm    loop LOOP1c
  244.  asm    mov    cx,[addx]    // any to finish up horizontally?
  245.  asm    jcxz    LOOP1a
  246.  asm    add    si,cx
  247.  asm    add    dx,cx
  248.  
  249.  LOOP1a:
  250.  asm    sub    di,[width]    // calculate next CGA line
  251.  asm    xor    di,0x2000
  252.  asm    inc    bl
  253.  asm    and    bl,1
  254.  asm    or    bl,bl
  255.  asm    jnz    LOOP1a0
  256.  asm    add    di,80
  257.  
  258.  LOOP1a0:
  259.  asm    dec    bh
  260.  asm    jnz    LOOP1
  261.  
  262.  asm    popf
  263.  asm    pop    ds
  264.  asm    pop    di
  265.  asm    pop    si
  266. }
  267.  
  268.  
  269. ////////////////////////////////////////////////////////////
  270. //
  271. // DoCGAMblit : handles output of masked EGA grabs to the screen
  272. //
  273. ////////////////////////////////////////////////////////////
  274. void DoCGAMblit(int x,int y,int width,int height,int yadd,int hadd)
  275. {
  276.  int i,j;
  277.  
  278.  if (noshow || SkipToStart)
  279.    return;
  280.  
  281.  if (nostacking)
  282.    {
  283.     globalx=x;
  284.     globaly=y;
  285.     yadd=hadd=0;
  286.    }
  287.  else
  288.  if (yadd || hadd)
  289.    {
  290.     char huge *CGAscrn=MK_FP(0xb800,0);
  291.  
  292.     for (j=globaly;j<globaly+yadd;j++)
  293.       for (i=globalx;i<globalx+width;i++)
  294.     *(CGAscrn+(j/2)*80+(j&1)*0x2000+i)=0x5555;
  295.  
  296.     for (j=globaly+yadd+height;j<height+globaly+yadd+hadd;j++)
  297.       for (i=globalx;i<globalx+width;i++)
  298.     *(CGAscrn+(j/2)*80+(j&1)*0x2000+i)=0x5555;
  299.    }
  300.  
  301.  CGAMblit(globalx,globaly+yadd,width,height,databuffer+offset);
  302.  if (!nostacking)
  303.    {
  304.     globalx+=width;
  305.     if (globalmaxh<height)
  306.       globalmaxh=height;
  307.     if (globalx>80-width)
  308.       {
  309.        globaly+=globalmaxh;
  310.        globalx=globalmaxh=0;
  311.       }
  312.    }
  313. }
  314.  
  315.  
  316. ////////////////////////////////////////////////////////////
  317. //
  318. // CGAMgrab: grabs any masked CGA shape from the screen buffer in main memory
  319. //           with INLINE asm for *FAST* grab!
  320. //         Of course, by John Romero!
  321. //
  322. // NOTE: I expect X & WIDTH to be in BYTE values, not pixels!
  323. //
  324. ////////////////////////////////////////////////////////////
  325. void CGAMgrab(int x,int y,int width,int height,unsigned offset,int optimize)
  326. {
  327.  unsigned j,maskoff,ESreg,DIreg,SIreg,DSreg,scrnwid,tmpset=0;
  328.  
  329.  scrnwid=CurrentLBM.width/4;
  330.  
  331.  //
  332.  // Does caller want vertical-seek optimization?
  333.  //
  334.  if (optimize)
  335.    {
  336.     Optimum.height=Optimum.y=0;
  337.  
  338.     for (i=y;i<y+height;i++)
  339.       {
  340.        for (j=x;j<x+width;j++)
  341.      if (*(maskscreen+i*scrnwid+j)!=0xff)
  342.        { Optimum.y=i; break; }
  343.        if (Optimum.y)
  344.      break;
  345.       }
  346.  
  347.     for (i=y+height-1;i>=0;i--)
  348.       {
  349.        for (j=x;j<x+width;j++)
  350.      if (*(maskscreen+i*scrnwid+j)!=0xff)
  351.        { Optimum.height=i-y; break; }
  352.        if (Optimum.height)
  353.      break;
  354.       }
  355.  
  356.     if (Optimum.height && Optimum.height!=height)
  357.       height=Optimum.height-(Optimum.y-y)+1;
  358.  
  359.     if (Optimum.y && Optimum.y!=y)
  360.       y=Optimum.y;
  361.    }
  362.  
  363.  
  364.  // FROM
  365.  SIreg=FP_OFF(maskscreen)+((scrnwid*y+x)&15);
  366.  DSreg=FP_SEG(maskscreen)+((scrnwid*y+x)/16);
  367.  
  368.  // TO
  369.  ESreg=FP_SEG(databuffer+offset);
  370.  DIreg=FP_OFF(databuffer+offset);
  371.  
  372.  asm        push    si
  373.  asm        push    di
  374.  asm        push    ds
  375.  
  376.  asm        mov    bx,[height]
  377.  asm        mov    dx,[width]
  378.  
  379.  asm        mov    es,[ESreg]
  380.  asm        mov    di,[DIreg]
  381.  asm        mov    si,[SIreg]
  382.  asm        mov    ax,[DSreg]
  383.  asm        mov    ds,ax
  384.  asm        cld
  385.  
  386.  LOOP0:
  387.  
  388.  asm        mov    cx,dx
  389.  LOOP00:
  390.  asm        lodsb
  391.  asm        or    al,al
  392.  asm        jz    LOOP01
  393.  asm        mov    [tmpset],1
  394.  
  395.  LOOP01:
  396.  asm        stosb
  397.  asm        loop    LOOP00
  398.  
  399.  asm        sub    si,dx
  400.  asm        add    si,[scrnwid]
  401.  asm        dec    bx
  402.  asm        jnz    LOOP0
  403.  
  404.  asm        pop    ds
  405.  asm        pop    di
  406.  asm        pop    si
  407.  
  408.  maskoff=DIreg;
  409.  
  410.  // FROM
  411.  SIreg=FP_OFF(lbmscreen)+((scrnwid*y+x)&15);
  412.  DSreg=FP_SEG(lbmscreen)+((scrnwid*y+x)/16);
  413.  
  414.  // TO
  415.  DIreg+=width*height;
  416.  
  417.  asm        push    si
  418.  asm        push    di
  419.  asm        push    ds
  420.  
  421.  asm        mov    dx,[width]
  422.  
  423.  asm        mov    es,[ESreg]
  424.  asm        mov    di,[DIreg]    // DI=CGA data offset
  425.  asm        mov    si,[SIreg]    // SI=CGA screen offset
  426.  asm        mov    ds,[DSreg]
  427.  asm        mov    bx,[maskoff]    // BX=mask offset
  428.  asm        mov    ah,[BYTE PTR height]
  429.  
  430.  LOOP1:
  431.  asm        mov    cx,dx
  432.  
  433.  LOOP2:
  434.  asm        lodsb            // get CGA data
  435.  asm        mov    ch,[es:bx]    // get mask byte
  436.  asm        xor    ch,0xff        // and invert it!
  437.  asm        and    al,ch        // AND with mask
  438.  asm        xor    ch,ch        // make sure LOOP keeps going!
  439.  asm        stosb            // store
  440.  asm        inc    bx        // next mask byte
  441.  asm        loop LOOP2        // do all CGA bytes
  442.  
  443.  asm        sub    si,dx
  444.  asm        add    si,[scrnwid]
  445.  asm        dec    ah
  446.  asm        jnz    LOOP1
  447.  
  448.  asm        pop    ds
  449.  asm        pop    di
  450.  asm        pop    si
  451.  
  452.  //
  453.  // SEE IF WE NEED TO ELIMINATE THE MASK & SET THE
  454.  // BIT IN THE PACKED-BIT ARRAY. MASK-ELIMINATION IS
  455.  // DONE BY MOVING THE TILE DATA BACK OVER THE MASK.
  456.  //
  457.  setbit=tmpset^1;
  458.  
  459.  if (bit && setbit)
  460.    {
  461.     char masks[8]={0x80,0x40,0x20,0x10,8,4,2,1};
  462.     unsigned psize=width*height,domove=0;
  463.  
  464.     switch(type)
  465.     {
  466.      case TILE8MTYPE:
  467.      case ALT8MTYPE:
  468.        if (!cmpt8)
  469.      break;
  470.  
  471.        T8bit[T8whichbit/8]|=masks[T8whichbit%8];
  472.        domove=1;
  473.        break;
  474.      case TILE16MTYPE:
  475.      case ALT16MTYPE:
  476.        T16bit[T16whichbit/8]|=masks[T16whichbit%8];
  477.        domove=1;
  478.        break;
  479.      case TILE32MTYPE:
  480.      case ALT32MTYPE:
  481.        T32bit[T32whichbit/8]|=masks[T32whichbit%8];
  482.        domove=1;
  483.     }
  484.  
  485.     if (domove)
  486.       {
  487.        asm    push    si
  488.        asm    push    di
  489.        asm    push    ds
  490.  
  491.        asm    mov    si,[DIreg]
  492.        asm    mov    ax,[ESreg]
  493.        asm    mov    ds,ax
  494.        asm    mov    es,ax        // ES:DI - mask data
  495.        asm    mov    di,si
  496.        asm    add    si,[psize]    // DS:SI = tile data
  497.  
  498.        asm    mov    cx,[psize]    // move all tile data
  499.        asm    cld            // move forwards
  500.        asm    rep movsb
  501.  
  502.        asm    pop    ds
  503.        asm    pop    di
  504.        asm    pop    si
  505.       }
  506.    }
  507.  
  508. }
  509.